/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package gui;

import core.exceptions.DBAccessException;
import core.objects.Author;
import core.objects.BaseObject;
import core.objects.Book;
import core.objects.BookComment;
import core.objects.Category;
import core.objects.Country;
import core.objects.Publisher;
import core.objects.User;
import core.objects.UserComment;
import core.objects.enums.GenderEnum;
import db.DBAccessEngine;
import db.IDBAccess;
import db.threads.DBAccessThread;
import db.threads.IDBAccessThread;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Image;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
import parsing.google.GoogleAPI;

/**
 *
 * @author abadi
 */
public class GUIUtils {

    static String getTextFromPasswordField(JPasswordField jpf) {
        try {
            return jpf.getDocument().getText(0, jpf.getDocument().getLength());
        } catch (BadLocationException ex) {
            return "";
        }
    }

    static void setURLLink(final JLabel jl, final String url, boolean isLinkFormat) {
        jl.setCursor(new java.awt.Cursor(java.awt.Cursor.HAND_CURSOR));
        jl.setFont(new java.awt.Font("Trebuchet MS", 0, 13)); // NOI18N
        jl.setForeground(new java.awt.Color(255, 255, 255));
        if (isLinkFormat) {
            jl.setText("<html>[<u>" + jl.getText().replace("[", "").replace("]", "") + "</u>]</html>");
        }

        if (url == null || url.equals("")) {
            return;
        }
        jl.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
			public void mouseClicked(java.awt.event.MouseEvent evt) {
                try {
                    // open the default web browser for the HTML page
                    Desktop.getDesktop().browse(URI.create(url.replace("\"", "").replace(' ', '_')));
                } catch (Exception e) {
                    GUIUtils.showMessageError(new Exception("Error opening wikipedia page", e), jl.getParent());
                }
            }
        });
    }

    static void setImageAtSize(JLabel jLabelImage, int width, int height, byte[] image) {
        ImageIcon icon = new ImageIcon(image);
        setImageIcon(jLabelImage, width, height, icon);
    }

    public static void setImageAtSize(JLabel jLabelImage, int width, int height, String path) {
        ImageIcon icon;
		try {
			icon = new ImageIcon(ImageIO.read(GUIUtils.class.getResourceAsStream(path)));
	        setImageIcon(jLabelImage, width, height, icon);
		} catch (IOException e) {
			//do nothing, keep whatever placeholder was set
		}
    }

    public static void setImageAtSize(JLabel jLabelImage, int width, int height, URL url) {
        ImageIcon icon = new ImageIcon(url);
        setImageIcon(jLabelImage, width, height, icon);
    }

    static private void setImageIcon(final JLabel jLabelImage, final int width, final int height, final ImageIcon icon) {
        DBAccessThread.invoke(new IDBAccessThread() {
            @Override
            public Object onCreateQuery() throws DBAccessException {
                Image im = icon.getImage();
                return im;
            }

            @Override
            public void onAccessFinished(Object response) {
                icon.setImage(((Image) response).getScaledInstance(width, height, Image.SCALE_DEFAULT));
                jLabelImage.setIcon(icon);
                jLabelImage.setMaximumSize(new Dimension(width, height));
                jLabelImage.setMinimumSize(new Dimension(width, height));
                jLabelImage.setPreferredSize(new Dimension(width, height));
            }

            @Override
            public void onAccessFailed(DBAccessException e) {
                showMessageError(e, jLabelImage);
            }
        });
    }

    public static void setJComponentFontAndColor(JComponent jl, int size) {
        jl.setFont(new java.awt.Font("Trebuchet MS", Font.BOLD, size)); // NOI18N
        jl.setForeground(new java.awt.Color(153, 255, 153));
    }

    public static void setJComponentFontAndColorNonBold(JComponent jl, int size) {
        jl.setFont(new java.awt.Font("Trebuchet MS", Font.PLAIN, size)); // NOI18N
        jl.setForeground(new java.awt.Color(153, 255, 153));
    }

    /**
     * If string is empty returns null, else returns the string
     *
     * @param str
     * @return
     */
    static String checkIfEmpy(String str) {
        if ("".equals(str)) {
            return null;
        } else {
            return str;
        }
    }

    static void handleJTextFieldFocusGained(JTextComponent jtc, String defaultText) {
        if (jtc.getText().equals(defaultText)) {
            jtc.setText("");
        } else {
            jtc.setSelectionStart(0);
            jtc.setSelectionEnd(jtc.getText().length());
        }
    }

    static void handleJTextFieldFocusLost(JTextComponent jtc, String defaultText) {
        if (jtc.getText().equals("")) {
            jtc.setText(defaultText);
        }
    }

    @SuppressWarnings("unchecked")
	static Book setGoogleDetails(Book book, Component comp) {
        Book b = (Book) GoogleAPI.requestBookByISBN(book.getISBN());
        if (b != null) {
            if (book.getDescription() == null) {
                String desc = b.getDescription() == null ? "" : b.getDescription();
                book.setDescription(desc);
            }
            if (book.getGoogleRating() == 0.0) {
                book.setGoogleRating(b.getGoogleRating());
            }
            if (book.getLanguage() == null) {
                String leng = b.getLanguage() == null ? "" : b.getLanguage();
                book.setLanguage(leng);
            }
            try {
                ((IDBAccess<Book>) DBAccessEngine.Book()).update(book);
            } catch (DBAccessException ex) {
                GUIUtils.showMessageError(ex, comp);
            }
        }
        return b;
    }

    @SuppressWarnings("unchecked")
	public static BookComment addBookComment(Book book, User user, String comment, int rating, Component comp) {
        BookComment bookComment = new BookComment(0, book.getID(), user.getID(), comment, rating);
        try {
            ((IDBAccess<BookComment>) DBAccessEngine.BookComment()).insert(bookComment);
        } catch (DBAccessException ex) {
            showMessageError(ex, comp);
        }
        return bookComment;
    }

    @SuppressWarnings("unchecked")
	public static UserComment addUserComment(User commented, User commenter, String comment, int rating, Component comp) {
        UserComment userComment = new UserComment(0, commented.getID(), commenter.getID(), comment, rating);
        try {
            ((IDBAccess<UserComment>) DBAccessEngine.UserComment()).insert(userComment);
        } catch (DBAccessException ex) {
            showMessageError(ex, comp);
        }
        return userComment;
    }

    public static void showMessageError(DBAccessException e, Component comp) {
    	e.printStackTrace();
        JOptionPane.showMessageDialog(comp, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
    }

    public static void showMessageError(Exception e, Component comp) {
        JOptionPane.showMessageDialog(comp, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
    }

    public static String removeSecondsFromTimestamp(Timestamp timestamp) {
    	if (timestamp == null)
    		return null;
        return timestamp.toString().substring(0, 16);
    }

    static void initTextHeaderJlabel(JLabel jl, String text) {
        if (text == null || text.equals("")) {
            text = "";
        }
        jl.setText(jl.getText() + " " + text);
        GUIUtils.setJComponentFontAndColor(jl, 13);
    }

    static void initTextHeaderJlabel(JTextComponent jtc, String text) {
        initTextHeaderJlabel(jtc, text, false);
    }

    static void initTextHeaderJlabel(JTextComponent jtc, String text, boolean isOverridesText) {
        if (text == null || text.equals("")) {
            text = "";
        }
        if (isOverridesText) {
            jtc.setText(text);
        } else {
            jtc.setText(jtc.getText() + " " + text);
        }
        GUIUtils.setJComponentFontAndColor(jtc, 13);
    }

    static String listToString(List<? extends BaseObject> lst) {
        if (lst == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (BaseObject bo : lst) {
            if (sb.length() > 0) {
                sb.append(", ");
            }
            sb.append(bo.getName());
        }
        return sb.toString();
    }

    public static void mailto(String email, String subject,
            String body) throws IOException, URISyntaxException {
        
        Desktop desktop = Desktop.getDesktop();
        if (!desktop.isSupported(Desktop.Action.MAIL)) {
            throw new IOException("Mailing is not supported!");
        }
        String uriStr = String.format("mailto:%s?subject=%s&body=%s",
                email, // use semicolon ";" for Outlook!
                urlEncode(subject),
                urlEncode(body));
        desktop.mail(new URI(uriStr));
    }

    private static String urlEncode(String str) throws UnsupportedEncodingException {
        return URLEncoder.encode(str, "UTF-8").replace("+", "%20");
    }

    @SuppressWarnings("unchecked")
	public static void setBookPrameters(Book book, Component comp) {
        try {
            List<Category> categories = (List<Category>) DBAccessEngine.Book().selectAll(book.getID(), new Category(0, ""));
            List<Author> authors = (List<Author>) DBAccessEngine.Book().selectAll(book.getID(), new Author(0, ""));
            List<Publisher> publishers = (List<Publisher>) DBAccessEngine.Book().selectAll(book.getID(), new Publisher(0, ""));
            book.setAuthors((ArrayList<Author>) authors);
            book.setCategories((ArrayList<Category>) categories);
            book.setPublishers((ArrayList<Publisher>) publishers);
        } catch (DBAccessException ex) {
            showMessageError(ex, comp);
        }
    }

    static public void setProfileImageAtLabel(User user, JLabel imageLabel) {
        setProfileImageAtLabel(user, imageLabel, 60, 90);
    }

    static public void setProfileImageAtLabel(User user, JLabel imageLabel, int width, int height) {
        if (user.getImage() != null) {
            GUIUtils.setImageAtSize(imageLabel, width, height, user.getImage());
        } else if (user.getGender() != null && user.getGender().equals(GenderEnum.Male)) {
            GUIUtils.setImageAtSize(imageLabel, width, height, "/resources/man.png");
        } else if (user.getGender() != null && user.getGender().equals(GenderEnum.Female)) {
            GUIUtils.setImageAtSize(imageLabel, width, height, "/resources/woman.png");
        } else {
            GUIUtils.setImageAtSize(imageLabel, width, height, "/resources/noGender.png");
        }
    }

    @SuppressWarnings("unchecked")
	static public Country[] genCountriesArray() throws DBAccessException {
        List<Country> countriesLst = (List<Country>) DBAccessEngine.Country().selectAll();
        countriesLst.add(0, new Country(-1, ""));
        return listToArray(countriesLst);
    }

    static private Country[] listToArray(List<Country> ls) {
        return ls.toArray(new Country[0]);
    }

    static public Object[] reverse(Object[] arr) {
        List< Object> list = Arrays.asList(arr);
        Collections.reverse(list);
        return list.toArray();
    }

    static public JPanel getNotFoundPanel() {
        JPanel jPanelNotFound = new JPanel(new FlowLayout(FlowLayout.CENTER));
        JLabel sorryNoResultsFound = new JLabel(" No Results Found");
        jPanelNotFound.setBackground(new java.awt.Color(51, 153, 255));
        GUIUtils.setJComponentFontAndColor(sorryNoResultsFound, 35);
        sorryNoResultsFound.setForeground(Color.DARK_GRAY);
        JLabel image = new JLabel();
        GUIUtils.setImageAtSize(image, 230, 110, "/resources/sorry.png");
        jPanelNotFound.add(image);
        jPanelNotFound.add(sorryNoResultsFound);
        jPanelNotFound.setOpaque(false);
        //jPanelNotFound.setSize(new Dimension(jPanelNotFound.getWidth(), 3));
        return jPanelNotFound;
    }
}
